home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Contributed / SpriteWorld / SpriteWorld Examples / Tiling Demo / Tiling Demo.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-06  |  14.3 KB  |  529 lines  |  [TEXT/CWIE]

  1. ///--------------------------------------------------------------------------------------
  2. // Tiling Demo.c
  3. //
  4. // By Vern Jensen, August 1995
  5. ///--------------------------------------------------------------------------------------
  6.  
  7.  
  8. #include <SWIncludes.h>
  9. #include <SWGameUtils.h>
  10. #include <SWDitherDown.h>
  11. #include <SWFPSReport.h>
  12.  
  13. #include "SWApplication.h"
  14. #include "Tiling Demo.h"
  15.  
  16.  
  17. #define    kFullScreenWindow            true        // Makes the window fill the screen
  18. #define    kInterlacedMode                false        // Skips every other line
  19. #define kSyncToVBL                    false        // Syncs animation to VBL
  20. #define kWorldRectInset                0            // Makes SpriteWorld smaller than window
  21. #define kMaxFPS                        30            // Set to 0 for unrestricted speed
  22.  
  23. #define kNumDiamonds                10            // Number of diamonds
  24. #define kMaxDiamondMoveDelta        5            // Max speed for the diamonds
  25.  
  26. #define kTileWidth                    40            // Don't change these unless you
  27. #define kTileHeight                    40            // change the resource as well.
  28.  
  29.  
  30. enum tileIDs            // Meaningful values for the tileIDs
  31. {
  32.     kWallTile,
  33.     kBoardTile,
  34.     kMaxNumTiles
  35. };
  36.  
  37.  
  38.  
  39. /***********/
  40. /* Globals */
  41. /***********/
  42.  
  43. SpriteWorldPtr        gSpriteWorldP;
  44.  
  45. SpriteLayerPtr        gTopDiamondSpriteLayerP;
  46. SpriteLayerPtr        gBottomDiamondSpriteLayerP;
  47.     
  48. TileMapStructPtr    gTileMapStructP;
  49. SpritePtr            gBallSpriteP;
  50. WindowPtr            gWindowP;
  51.  
  52. DrawProcPtr            gSpriteDrawProc;
  53. short                gNumTileMapRows, gNumTileMapCols;
  54.  
  55.  
  56. ///--------------------------------------------------------------------------------------
  57. // Main
  58. ///--------------------------------------------------------------------------------------
  59.  
  60. void    main( void )
  61. {
  62.     Initialize(kNumberOfMoreMastersCalls);
  63.     
  64.     if (SWHasSystem7())
  65.     {
  66.         SetCursor(*GetCursor(watchCursor));
  67.         HideControlStrip();
  68.         SWSetCleanUpFunction(MyCleanUpFunction);
  69.         
  70.         CreateSpriteWorld();
  71.         SetUpTiling();
  72.         CreateSprites();
  73.         
  74.         SetCursor(&qd.arrow);
  75.         HideCursor();
  76.         
  77.         SetUpAnimation();
  78.         RunAnimation();
  79.         ShutDown();
  80.         
  81.         RestoreControlStrip();
  82.     }
  83.     else
  84.     {
  85.         CantRunOnThisMachine();
  86.     }
  87. }
  88.  
  89.  
  90. ///--------------------------------------------------------------------------------------
  91. // CreateSpriteWorld
  92. ///--------------------------------------------------------------------------------------
  93.  
  94. void    CreateSpriteWorld( void )
  95. {
  96.     Rect        offscreenRect, worldRect, windRect;
  97.     RgnHandle    mBarUpdateRgn;
  98.     OSErr        err;
  99.     
  100.     gWindowP = GetNewCWindow(kWindowResID, NULL, (WindowPtr)-1L);
  101.     
  102.     if (gWindowP != NULL)
  103.     {
  104.         if (kFullScreenWindow == true)
  105.         {
  106.             SizeWindow(gWindowP, qd.screenBits.bounds.right, 
  107.                     qd.screenBits.bounds.bottom, false);
  108.             MoveWindow(gWindowP, 0, 0, false);
  109.         }
  110.         else
  111.         {
  112.                 // Center window in screen
  113.             windRect = gWindowP->portRect;
  114.             CenterRect(&windRect, &qd.screenBits.bounds);
  115.             MoveWindow(gWindowP, windRect.left, windRect.top, false);
  116.         }
  117.         
  118.         ShowWindow(gWindowP);
  119.         SetPort(gWindowP);
  120.         mBarUpdateRgn = SWHideMenuBar(gWindowP); // Must be done *after* showing window!
  121.         EraseRgn(mBarUpdateRgn);
  122.         
  123.         if (kInterlacedMode)
  124.             PaintRect(&gWindowP->portRect);    // Blacken window for Interlaced mode
  125.     }
  126.     else
  127.         CantFindResource();
  128.     
  129.     
  130.     err = SWEnterSpriteWorld();
  131.     FatalError(err);
  132.  
  133.     
  134.     worldRect = gWindowP->portRect; 
  135.     InsetRect(&worldRect, kWorldRectInset, kWorldRectInset);
  136.     
  137.     
  138.         // Set size of offscreen area
  139.     offscreenRect = worldRect;
  140.     OffsetRect(&offscreenRect, -offscreenRect.left, -offscreenRect.top);
  141.     
  142.  
  143.         // Make offscreen area evenly divisible by tile width & height
  144.     if ( (offscreenRect.right/kTileWidth)*kTileWidth != offscreenRect.right)
  145.         offscreenRect.right = (offscreenRect.right/kTileWidth)*kTileWidth + kTileWidth;
  146.     
  147.     if ( (offscreenRect.bottom/kTileHeight)*kTileHeight != offscreenRect.bottom)
  148.         offscreenRect.bottom = (offscreenRect.bottom/kTileHeight)*kTileHeight + kTileHeight;
  149.     
  150.     
  151.     gNumTileMapRows = offscreenRect.bottom / kTileHeight;
  152.     gNumTileMapCols = offscreenRect.right / kTileWidth;
  153.     
  154.  
  155.     err = SWCreateSpriteWorldFromWindow(&gSpriteWorldP, (CWindowPtr)gWindowP, 
  156.             &worldRect, &offscreenRect, 0);
  157.     FatalError(err);
  158.     
  159.     
  160.         // Set the gSpriteDrawProc before loading sprites
  161.     if ( SW_PPC )
  162.     {
  163.         if (gSpriteWorldP->pixelDepth >= 8)
  164.             gSpriteDrawProc = BlitPixieMaskDrawProc;
  165.         else
  166.             gSpriteDrawProc = SWStdSpriteDrawProc;
  167.     }
  168.     else
  169.     {
  170.         if (gSpriteWorldP->pixelDepth >= 8)
  171.             gSpriteDrawProc = BlitPixieCompiledSpriteDrawProc;
  172.         else
  173.             gSpriteDrawProc = BlitPixieAllBitMaskDrawProc;
  174.     }
  175. }
  176.  
  177.  
  178. ///--------------------------------------------------------------------------------------
  179. // SetUpTiling
  180. ///--------------------------------------------------------------------------------------
  181.  
  182. void    SetUpTiling( void )
  183. {
  184.     short        row, col;
  185.     OSErr        err;
  186.     
  187.     
  188.         // Must be done before we can load the tiles.
  189.     err = SWInitTiling(gSpriteWorldP, kTileHeight, kTileWidth, kMaxNumTiles);
  190.     FatalError(err);
  191.     
  192.     err = SWCreateTileMap(&gTileMapStructP, gNumTileMapRows, gNumTileMapCols);
  193.     FatalError(err);
  194.     
  195.     SWInstallTileMap(gSpriteWorldP, gTileMapStructP, 0);
  196.     
  197.     
  198.     // For demonstration purposes, we've decided to load the tiles from CICN
  199.     // resources here, and load them from PICT resources in the Scrolling Demo.
  200.     
  201.         // Load the wall tile
  202.     err = SWLoadTileFromCicnResource(
  203.         gSpriteWorldP, 
  204.         kWallTile,                // tileID
  205.         200,                     // CICN resource ID
  206.         kSolidMask,                // maskType
  207.         kMaskIsNotPartialMask);    // partialMask?
  208.     FatalError(err);
  209.         
  210.         // Load the board ("wire") tile
  211.     err = SWLoadTileFromCicnResource(
  212.         gSpriteWorldP, 
  213.         kBoardTile,                // tileID
  214.         201,                     // CICN resource ID
  215.         kFatMask,                // maskType
  216.         kMaskIsPartialMask);    // partialMask?
  217.     FatalError(err);
  218.  
  219.     
  220.     
  221.         // Initialize the values in the tileMap
  222.     for (row = 0; row < gNumTileMapRows; row++)
  223.     {
  224.         for (col = 0; col < gNumTileMapCols; col++)
  225.         {
  226.             if (row == 0 || col == 0 || row == gNumTileMapRows-1 || col == gNumTileMapCols-1)
  227.                 gTileMapStructP->tileMap[row][col] = kWallTile;
  228.             else
  229.                 gTileMapStructP->tileMap[row][col] = kBoardTile;
  230.         }
  231.     }
  232. }
  233.  
  234.  
  235. ///--------------------------------------------------------------------------------------
  236. // CreateSprites
  237. ///--------------------------------------------------------------------------------------
  238.  
  239. void    CreateSprites( void )
  240. {
  241.     SpritePtr            diamondSpriteP;
  242.     SpritePtr            tempSpriteP;
  243.     short                spriteNum;
  244.     Point                moveDelta, mousePoint;
  245.     Rect                moveBounds;
  246.     OSErr                err;
  247.     
  248.     
  249.         // Create the sprite layers
  250.     SWCreateSpriteLayer(&gTopDiamondSpriteLayerP);
  251.     SWCreateSpriteLayer(&gBottomDiamondSpriteLayerP);
  252.     FatalError(SWStickyError());
  253.     
  254.     
  255.     moveBounds = gSpriteWorldP->backRect;
  256.     InsetRect(&moveBounds, 40, 40);
  257.     
  258.         // create and set up the diamond sprites
  259.     for (spriteNum = 0; spriteNum < kNumDiamonds; spriteNum++)
  260.     {
  261.         if (spriteNum == 0)
  262.         {
  263.             err = SWCreateSpriteFromPictResource(gSpriteWorldP,
  264.                 &diamondSpriteP, 
  265.                 NULL,        // pointer to memory for sprite
  266.                 128,         // picture resource id
  267.                 128,         // mask resource id (we use self-masking)
  268.                 1,             // max frames
  269.                 kFatMask);    // mask type
  270.             FatalError(err);
  271.  
  272.             tempSpriteP = diamondSpriteP;
  273.             
  274.             if (gSpriteWorldP->pixelDepth >= 8)
  275.                 SWCompileSprite(diamondSpriteP);
  276.         }
  277.         else
  278.         {
  279.             err = SWCloneSprite(diamondSpriteP, &tempSpriteP, NULL);
  280.             FatalError(err);
  281.         }
  282.         
  283.  
  284.         SWSetSpriteMoveBounds(tempSpriteP, &moveBounds);
  285.         SWSetSpriteMoveProc(tempSpriteP, DiamondSpriteMoveProc);
  286.         
  287.         SWSetSpriteLocation(tempSpriteP, 
  288.                 GetRandom(40, gSpriteWorldP->backRect.right-80), 
  289.                 GetRandom(40, gSpriteWorldP->backRect.bottom-80));
  290.         
  291.         do
  292.         {
  293.             moveDelta.h = GetRandom(-kMaxDiamondMoveDelta, kMaxDiamondMoveDelta);
  294.             moveDelta.v = GetRandom(-kMaxDiamondMoveDelta, kMaxDiamondMoveDelta);
  295.         } while (!moveDelta.v || !moveDelta.h);
  296.         
  297.         SWSetSpriteMoveDelta(tempSpriteP, moveDelta.h, moveDelta.v);
  298.         SWSetSpriteDrawProc(tempSpriteP, gSpriteDrawProc);
  299.         err = SWAddSprite(gTopDiamondSpriteLayerP, tempSpriteP);
  300.         FatalError(err);
  301.     }
  302.     
  303.     
  304.         // Create the ball sprite
  305.     err = SWCreateSpriteFromCicnResource(gSpriteWorldP, &gBallSpriteP, NULL, 
  306.             128, 1, kFatMask);    
  307.     FatalError(err);
  308.     
  309.     if (gSpriteWorldP->pixelDepth >= 8)
  310.         SWCompileSprite(gBallSpriteP);
  311.     
  312.     
  313.         // Set up the ball sprite
  314.     err = SWAddSprite(gTopDiamondSpriteLayerP, gBallSpriteP);
  315.     FatalError(err);
  316.     SWSetSpriteMoveProc(gBallSpriteP, BallSpriteMoveProc);
  317.     SWSetSpriteDrawProc(gBallSpriteP, gSpriteDrawProc);
  318.     SWSetFrameHotSpot(gBallSpriteP->curFrameP, 20, 20);
  319.     GetMouse(&mousePoint);
  320.     SWSetSpriteLocation(gBallSpriteP, mousePoint.h, mousePoint.v);
  321.     
  322.     SWAddSpriteLayer(gSpriteWorldP, gBottomDiamondSpriteLayerP);    // Add bottom first, so it is drawn first
  323.     SWAddSpriteLayer(gSpriteWorldP, gTopDiamondSpriteLayerP);        // Add top last, so it is drawn last
  324.  
  325.     SWLockSpriteWorld(gSpriteWorldP);
  326.     
  327.     
  328.         // Test out the dithering routines in DitherDown.c. 
  329.         // See DitherDown.c for more info.
  330.     if (gSpriteWorldP->pixelDepth < 8)
  331.     {
  332.             // Dither the diamond sprite
  333.         DitherDownPict(128, diamondSpriteP->frameArray[0]->framePort);
  334.         LowerMaskDepth(128, diamondSpriteP->frameArray[0]->maskPort);
  335.         
  336.             // Dither the wall tile
  337.         DitherDownCicn(200, gSpriteWorldP->tileFrameArray[kWallTile]->framePort);
  338.     }
  339. }
  340.  
  341.  
  342. ///--------------------------------------------------------------------------------------
  343. // SetUpAnimation
  344. ///--------------------------------------------------------------------------------------
  345.  
  346. void    SetUpAnimation( void )
  347. {
  348.     SWSetSpriteWorldMaxFPS(gSpriteWorldP, kMaxFPS);
  349.     SWSyncSpriteWorldToVBL(gSpriteWorldP, kSyncToVBL);
  350.     SWSetCleanUpSpriteWorld(gSpriteWorldP);
  351.     
  352.     SWSetSpriteLayerUnderTileLayer(gBottomDiamondSpriteLayerP, 0);
  353.     
  354.     if (gSpriteWorldP->pixelDepth >= 8)        // 8-bit, 16-bit, and 32-bit blitter
  355.     {
  356.         SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, BlitPixieRectDrawProc);
  357.         SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, BlitPixieRectDrawProc);
  358.         SWSetPartialMaskDrawProc(gSpriteWorldP, BlitPixiePartialMaskDrawProc);
  359.     }
  360.     else if ( SW_68K )        // Use 68k-only AllBit blitter when in depths lower than 8-bits
  361.     {
  362.         SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, BlitPixieAllBitRectDrawProc);
  363.         SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, BlitPixieAllBitRectDrawProc);
  364.         SWSetPartialMaskDrawProc(gSpriteWorldP, BlitPixieAllBitPartialMaskDrawProc);
  365.     }
  366.     
  367.     if (kInterlacedMode)
  368.     {
  369.         SWSetFrameInterlacingMode(gSpriteWorldP->workFrameP, true, kSkipOddLines);
  370.         SWSetFrameInterlacingMode(gSpriteWorldP->windowFrameP, true, kSkipOddLines);
  371.     }
  372.     
  373.         // Make sure CopyBits, if used, doesn't try to colorize things
  374.     SWSetPortToWindow(gSpriteWorldP);
  375.     ForeColor(blackColor);
  376.     BackColor(whiteColor);
  377.  
  378.     SWDrawTilesInBackground(gSpriteWorldP);
  379.     SWUpdateSpriteWorld(gSpriteWorldP, true);
  380. }
  381.  
  382.  
  383. ///--------------------------------------------------------------------------------------
  384. //  RunAnimation
  385. ///--------------------------------------------------------------------------------------
  386.  
  387. void    RunAnimation( void )
  388. {
  389.     unsigned long        frames;
  390.     
  391.     frames = 0;
  392.     StartTimer();
  393.     
  394.     FatalError( SWStickyError() ); // Make sure no errors got past us during setup
  395.     
  396.     while (!Button())
  397.     {
  398.         SWProcessSpriteWorld(gSpriteWorldP);
  399.         FatalError( SWStickyError() );    // Make sure no errors occurred during a MoveProc, etc.
  400.         SWAnimateSpriteWorld(gSpriteWorldP);
  401.         
  402.         if (gSpriteWorldP->frameHasOccurred)
  403.             frames++;
  404.     }
  405.     
  406.     SWShowMenuBar(gWindowP);
  407.     ShowResults(frames);
  408. }
  409.  
  410.  
  411. ///--------------------------------------------------------------------------------------
  412. //  ShutDown (clean up and dispose of the SpriteWorld)
  413. ///--------------------------------------------------------------------------------------
  414.  
  415. void    ShutDown( void )
  416. {
  417.     SWUnlockSpriteWorld(gSpriteWorldP);
  418.     SWDisposeSpriteWorld(&gSpriteWorldP);
  419.     SWExitSpriteWorld();
  420.     
  421.     FlushEvents(everyEvent, 0);
  422.     InitCursor();
  423. }
  424.  
  425.  
  426. ///--------------------------------------------------------------------------------------
  427. //  MyCleanUpFunction - called if an error occurs, to clean up before quitting
  428. ///--------------------------------------------------------------------------------------
  429.  
  430. void    MyCleanUpFunction( void )
  431. {
  432.     SWShowMenuBar(gWindowP);
  433.     
  434.     RestoreControlStrip();
  435. }
  436.  
  437.  
  438. ///--------------------------------------------------------------------------------------
  439. //  BallSpriteMoveProc - makes the ball follow the mouse
  440. ///--------------------------------------------------------------------------------------
  441.  
  442. SW_FUNC void BallSpriteMoveProc(SpritePtr srcSpriteP)
  443. {
  444.     Point                mousePoint;
  445.     SpritePtr            tempSpriteP;
  446.     EventRecord            event;
  447.     short                theChar;
  448.     
  449.     
  450.         // Move the ball sprite
  451.     GetMouse(&mousePoint);
  452.     
  453.         // Subtract any offset from worldRect to window if a worldRect is used
  454.     mousePoint.h -= gSpriteWorldP->windRect.left;
  455.     mousePoint.v -= gSpriteWorldP->windRect.top;
  456.     
  457.         // This sprite uses a hotSpot of 20,20, so all we have to do is move its
  458.         // hotPoint to the current mouse location, and it will appear centered properly
  459.     SWMoveSprite(srcSpriteP, mousePoint.h, mousePoint.v);
  460.     
  461.     
  462.         // Change ball sprite layers if the spacebar was hit
  463.     while ( GetOSEvent(keyDownMask, &event) )
  464.     {
  465.         theChar = (event.message & charCodeMask);
  466.         
  467.         if (theChar == ' ')
  468.         {
  469.             if (srcSpriteP->parentSpriteLayerP == gBottomDiamondSpriteLayerP)
  470.             {
  471.                 SWRemoveSprite(srcSpriteP);
  472.                 SWAddSprite(gTopDiamondSpriteLayerP, srcSpriteP);
  473.             }
  474.             else
  475.             {
  476.                 SWRemoveSprite(srcSpriteP);
  477.                 SWAddSprite(gBottomDiamondSpriteLayerP, srcSpriteP);
  478.             }
  479.         }
  480.     }
  481.     
  482.         
  483.         // Check for collision with diamonds in same layer as ball //
  484.  
  485.     tempSpriteP = srcSpriteP->parentSpriteLayerP->headSpriteP;
  486.  
  487.     while (tempSpriteP != NULL)
  488.     {
  489.             // are the sprite’s rectangles overlapping?
  490.         if (tempSpriteP != gBallSpriteP &&
  491.             (tempSpriteP->destFrameRect.top < gBallSpriteP->destFrameRect.bottom) &&
  492.             (tempSpriteP->destFrameRect.bottom > gBallSpriteP->destFrameRect.top) &&
  493.             (tempSpriteP->destFrameRect.left < gBallSpriteP->destFrameRect.right) &&
  494.             (tempSpriteP->destFrameRect.right > gBallSpriteP->destFrameRect.left))
  495.         {
  496.                 // Check to see if the masks overlap
  497.             if ( SWRegionCollision(tempSpriteP, gBallSpriteP)) 
  498.             {
  499.                     // Switch diamond position above/under tiles
  500.                 if (tempSpriteP->parentSpriteLayerP == gBottomDiamondSpriteLayerP)
  501.                 {
  502.                     SWRemoveSprite(tempSpriteP);
  503.                     SWAddSprite(gTopDiamondSpriteLayerP, tempSpriteP);
  504.                 }
  505.                 else
  506.                 {
  507.                     SWRemoveSprite(tempSpriteP);
  508.                     SWAddSprite(gBottomDiamondSpriteLayerP, tempSpriteP);
  509.                 }
  510.             }
  511.         }
  512.         
  513.         tempSpriteP = tempSpriteP->nextSpriteP;
  514.     }
  515. }
  516.  
  517.  
  518. ///--------------------------------------------------------------------------------------
  519. //  DiamondSpriteMoveProc
  520. ///--------------------------------------------------------------------------------------
  521.  
  522.  
  523. SW_FUNC void DiamondSpriteMoveProc(SpritePtr ballSpriteP)
  524. {    
  525.     SWOffsetSprite(ballSpriteP, ballSpriteP->horizMoveDelta, ballSpriteP->vertMoveDelta);
  526.     (void)SWBounceSprite(ballSpriteP);
  527. }
  528.  
  529.